﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Web;
using System.Web.Configuration;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Xml;
using AlipaySDK.Dto.Payment;
using AlipaySDK.Helper;
using Common.Logging;
using In.Api.Dto.HisWs;
using In.Api.Dto.YBWs;
using Newtonsoft.Json;
using OutDbContext;
using Rmq.Center;
using User.Api.BizExtensions;
using User.Api.Dto.Bill;
using User.Api.Helpers;
using User.Api.HttpClients;

namespace User.Api.Controllers
{
    public class BillController : ApiController
    {
        private static readonly ILog Logger = LogManager.GetLogger(typeof(BillController));
        private GdsfybjyWeiXinEntities _ctx;

        private static readonly object OrderNoLocker = new object();
        private static readonly object PayNotifyLocker = new object();

        protected override void Initialize(HttpControllerContext controllerContext)
        {
            _ctx = new GdsfybjyWeiXinEntities();
            base.Initialize(controllerContext);
        }

        protected override void Dispose(bool disposing)
        {
            _ctx.Dispose();
            base.Dispose(disposing);
        }

        /// <summary>
        /// 获取待缴费单列表
        /// </summary>
        /// <param name="cardId"></param>
        /// <returns></returns>
        [HttpGet]
        [ActionName("GetBillList")]
        public GetBillListResponse GetBillList(int cardId)
        {
            var azUser = AzUser.GetInApi(Request);
            var card = _ctx.HospCards.FirstOrDefault(x => x.CardId == cardId && x.WxUserId == azUser.UserId);
            if (card == null)
            {
                return new GetBillListResponse
                {
                    ResultCode = "1",
                    ResultMsg = "找不到就诊卡信息"
                };
            }

            //获取院内webservice
            var request = new GetPrescriptionListRequest();
            string currentDay = DateTime.Now.ToString("yyyy-MM-dd");
            request.CardNo = card.CardNo;
            //request.StartDate = currentDay;
            //request.EndDate = currentDay;

            GetPrescriptionListResponse response;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg = httpClient.PostAsJsonAsync("HisSp/GetPrescriptions", request).Result;
                responseMsg.EnsureSuccessStatusCode();
                response = responseMsg.Content.ReadAsAsync<GetPrescriptionListResponse>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内获取缴费单Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                return new GetBillListResponse
                {
                    ResultCode = "2",
                    ResultMsg = "获取缴费单信息超时"
                };
            }

            if (response.ResultCode != "0")
            {
                return new GetBillListResponse
                {
                    ResultCode = "3",
                    ResultMsg = response.ResultDesc
                };
            }

            return new GetBillListResponse
            {
                ResultCode = "0",
                ResultMsg = "",
                Bills = response.PrescList
                    .Where(x => x.PrescDate == DateTime.Now.ToString("yyyy-MM-dd")
                     && x.PayMoney.ToDecimalOrDefault() > 0)
                    .Select(x => new GetBillListResponse.BillInfo
                    {
                        ClinicNo = x.PrescNo,
                        PrescMoney = x.PayMoney.ToDecimalOrDefault().ToString("F2"),
                        OrderDept = x.PrescDept,
                        OrderDate = x.PrescDate,
                        //DoctorId = x.DoctorId,
                        //SettleCode = x.SettleCode
                    }).ToList()
            };
        }

        /// <summary>
        /// 生成缴费订单
        /// </summary>
        /// <param name="cardId"></param>
        /// <param name="clinicNo"></param>
        /// <param name="prescMoney"></param>
        /// <param name="orderDept"></param>
        /// <param name="orderDate"></param>
        /// <returns></returns>
        [HttpGet]
        [ActionName("CreateBillOrder")]
        public CreateBillOrderResponse CreateBillOrder(int cardId, string clinicNo, string prescMoney,
            string orderDept, string orderDate)
        {
            var azUser = AzUser.GetInApi(Request);

            var card = _ctx.HospCards.FirstOrDefault(x => x.CardId == cardId && x.WxUserId == azUser.UserId);
            if (card == null)
            {
                return new CreateBillOrderResponse
                {
                    ResultCode = "1",
                    ResultMsg = "找不到就诊卡信息"
                };
            }

            // 获取消费单明细
            var billDetailRequest = new GetPrescriptionDetailRequest();
            billDetailRequest.PrescNo = clinicNo;
            billDetailRequest.CardNo = card.CardNo;

            GetPrescriptionDetailResponse billDetailResponse;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg = httpClient.PostAsJsonAsync("HisSp/GetPrescriptionDetail", billDetailRequest).Result;
                responseMsg.EnsureSuccessStatusCode();
                billDetailResponse = responseMsg.Content.ReadAsAsync<GetPrescriptionDetailResponse>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内获取缴费单明细Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                return new CreateBillOrderResponse
                {
                    ResultCode = "2",
                    ResultMsg = "获取缴费单明细超时"
                };
            }

            if (billDetailResponse.ResultCode != "0")
            {
                return new CreateBillOrderResponse
                {
                    ResultCode = "2",
                    ResultMsg = billDetailResponse.ResultDesc
                };
            }

            // 为了避免医生 在同一个 就诊流水号 上再次开单造成患者无法支付的情况，对于 未支付 和 缴费成功 的情况我们可以 再次生成订单
            // 未支付但使用了医保的订单，需要医保退费处理
            var billOrder = _ctx.BillOrders
                .FirstOrDefault(x =>
                    x.CardNo == card.CardNo
                    && x.ClinicNo == clinicNo
                    && x.OrderDate == orderDate);

            if (billOrder != null)
            {
                if (billOrder.OrderStatus == BillOrderExtensions.OrderStatus.支付中.ToInt32()
                    || billOrder.OrderStatus == BillOrderExtensions.OrderStatus.支付成功.ToInt32()
                    || billOrder.OrderStatus == BillOrderExtensions.OrderStatus.缴费中.ToInt32())
                {
                    return new CreateBillOrderResponse
                    {
                        ResultCode = "3",
                        ResultMsg = "系统正在处理您的订单请耐心等候，大约需要15分钟"
                    };
                }
                else
                {
                    if (billOrder.OrderStatus == BillOrderExtensions.OrderStatus.未支付.ToInt32())
                    {
                        billOrder.OrderStatus = BillOrderExtensions.OrderStatus.支付失败.ToInt32();
                        _ctx.SaveChanges();

                        if (billOrder.YiBaoStatus == BillOrderExtensions.YiBaoStatus.使用了医保.ToInt32()
                        && !string.IsNullOrEmpty(billOrder.YiBaoJydjh))
                        {
                            billOrder.YiBaoStatus = BillOrderExtensions.YiBaoStatus.取消医保中.ToInt32();
                            _ctx.SaveChanges();

                            // 执行医保退费操作
                            var ybReturnRequest = new YBReturnChargesRequest();
                            ybReturnRequest.CardNo = billOrder.CardNo;
                            ybReturnRequest.Jydjh = billOrder.YiBaoJydjh;

                            YBReturnChargesResponse ybReturnResponse;
                            try
                            {
                                var httpClient = InHttpClient.GetClient();
                                var responseMsg = httpClient.PostAsJsonAsync("YBWs/YBReturnCharges", ybReturnRequest).Result;
                                responseMsg.EnsureSuccessStatusCode();
                                ybReturnResponse = responseMsg.Content.ReadAsAsync<YBReturnChargesResponse>().Result;

                                if (ybReturnResponse.ResultCode != "0")
                                {
                                    billOrder.YiBaoStatus = BillOrderExtensions.YiBaoStatus.取消医保失败.ToInt32();
                                    _ctx.SaveChanges();
                                }
                                else
                                {
                                    billOrder.YiBaoStatus = BillOrderExtensions.YiBaoStatus.取消了医保.ToInt32();
                                    _ctx.SaveChanges();
                                }
                            }
                            catch (Exception ex)
                            {
                                Logger.ErrorFormat("调用院内医保退费Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                                billOrder.YiBaoStatus = BillOrderExtensions.YiBaoStatus.取消医保失败.ToInt32();
                                _ctx.SaveChanges();
                            }
                        }
                    }

                    if (billOrder.YiBaoStatus == BillOrderExtensions.YiBaoStatus.取消医保中.ToInt32()
                        && !string.IsNullOrEmpty(billOrder.YiBaoJydjh))
                    {
                        return new CreateBillOrderResponse
                        {
                            ResultCode = "4",
                            ResultMsg = "系统正在处理医保，请稍后重试"
                        };
                    }
                    if (billOrder.YiBaoStatus == BillOrderExtensions.YiBaoStatus.取消医保失败.ToInt32()
                        && !string.IsNullOrEmpty(billOrder.YiBaoJydjh))
                    {
                        // 指导用户去窗口缴费
                        return new CreateBillOrderResponse
                        {
                            ResultCode = "5",
                            ResultMsg = "医保缴费失败，请到门诊缴费窗口进行缴费"
                        };
                    }
                }
            }

            var needGetYiBao = false;

            var getPatientRequest = new GetPatientInfoRequest();
            getPatientRequest.CardNo = card.CardNo;
            getPatientRequest.CardType = card.CardType.GetValueOrDefault().ToString();
            GetPatientInfoResponse getPatientResponse;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg = httpClient.PostAsJsonAsync("HisSp/GetPatientInfo", getPatientRequest).Result;
                responseMsg.EnsureSuccessStatusCode();
                getPatientResponse = responseMsg.Content.ReadAsAsync<GetPatientInfoResponse>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内获取病人信息Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                return new CreateBillOrderResponse
                {
                    ResultCode = "6",
                    ResultMsg = "获取就诊人信息超时"
                };
            }

            if (getPatientResponse.ResultCode != "0")
            {
                return new CreateBillOrderResponse
                {
                    ResultCode = "7",
                    ResultMsg = getPatientResponse.ResultDesc
                };
            }

            needGetYiBao = getPatientResponse.PatientInfo.FeeType == "广州医保" && prescMoney.ToDecimalOrDefault() > 0;

            var newOrderNo = GenerateNewOrderNo();

            var newBillOrder = new BillOrder
            {
                WxUserId = azUser.UserId,
                CardNo = card.CardNo,
                CardType = card.CardType.ToString(),
                CardName = card.PatientName,
                ClinicNo = clinicNo,
                OrderNo = newOrderNo,
                OrderDate = orderDate,
                OrderDept = orderDept,
                OrderStatus = BillOrderExtensions.OrderStatus.未支付.ToInt32(),
                PrescMoney = prescMoney.ToDecimalOrDefault(),
                PayState = BillOrderExtensions.PayState.未付款.ToInt32().ToString(),
                CreateTime = DateTime.Now,
                YiBaoStatus = BillOrderExtensions.YiBaoStatus.未使用医保.ToInt32(),
                AliPayType = "WAP"
            };

            if (needGetYiBao)
            {
                var getYbRequest = new GetYBChargesRequest();
                getYbRequest.CardNo = card.CardNo;
                getYbRequest.ClinicNo = clinicNo;
                getYbRequest.Zfy = prescMoney;

                GetYBChargesResponse getYbResponse;
                try
                {
                    var httpClient = InHttpClient.GetClient();
                    var responseMsg = httpClient.PostAsJsonAsync("YBWs/GetYBCharges", getYbRequest).Result;
                    responseMsg.EnsureSuccessStatusCode();
                    getYbResponse = responseMsg.Content.ReadAsAsync<GetYBChargesResponse>().Result;

                    if (getYbResponse.ResultCode != "0")
                    {
                        newBillOrder.YiBaoStatus = BillOrderExtensions.YiBaoStatus.获取医保失败.ToInt32();
                        newBillOrder.Remark = getYbResponse.ResultDesc;
                    }
                    else
                    {
                        var cost = getYbResponse.Costs.ToDecimalOrDefault();
                        var charges = getYbResponse.Charges.ToDecimalOrDefault();

                        if (cost < 0 || charges < 0 || (cost + charges != prescMoney.ToDecimalOrDefault()))
                        {
                            // 返回医保金额数据出错，当成取消医保失败，让用户去人工窗口缴费
                            newBillOrder.YiBaoStatus = BillOrderExtensions.YiBaoStatus.取消医保失败.ToInt32();
                            newBillOrder.Remark = "医保缴费失败，请到门诊缴费窗口进行缴费";
                            newBillOrder.OrderStatus = BillOrderExtensions.OrderStatus.支付失败.ToInt32();
                        }
                        else
                        {
                            newBillOrder.YiBaoStatus = BillOrderExtensions.YiBaoStatus.使用了医保.ToInt32();
                            newBillOrder.YiBaoIndiId = getYbResponse.IndiId;
                            newBillOrder.YiBaoJydjh = getYbResponse.Jydjh;
                            newBillOrder.YibaoMoney = getYbResponse.Charges.ToDecimalOrDefault();
                            newBillOrder.PersonalMoney = getYbResponse.Costs.ToDecimalOrDefault();
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("调用院内获取获取医保费用Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                    // ?? 是定 获取医保失败使用微信自费缴费 还是 定 取消医保失败让用户去人工窗口缴费
                    newBillOrder.YiBaoStatus = BillOrderExtensions.YiBaoStatus.取消医保失败.ToInt32();
                    newBillOrder.Remark = "医保缴费失败，请到门诊缴费窗口进行缴费";
                    newBillOrder.OrderStatus = BillOrderExtensions.OrderStatus.支付失败.ToInt32();
                }
            }

            _ctx.BillOrders.Add(newBillOrder);
            _ctx.SaveChanges();

            foreach (var item in billDetailResponse.PrescItemList)
            {
                var newBillOrderItem = new BillOrderItem
                {
                    BillOrderId = newBillOrder.Id,
                    //Account = item.Account,
                    //ItemPrice = item.ItemPrice.ToDecimalOrDefault(),
                    Money = item.Money.ToDecimalOrDefault(),
                    Name = item.ItemName,
                    Type = item.Type
                    //Unit = item.Unit
                };

                _ctx.BillOrderItems.Add(newBillOrderItem);
            }
            _ctx.SaveChanges();

            if (newBillOrder.YiBaoStatus == BillOrderExtensions.YiBaoStatus.取消医保失败.ToInt32())
            {
                // 指导用户去窗口缴费
                return new CreateBillOrderResponse
                {
                    ResultCode = "5",
                    ResultMsg = "医保缴费失败，请到门诊缴费窗口进行缴费"
                };
            }

            var response = new CreateBillOrderResponse();
            response.ResultCode = "0";
            response.ResultMsg = "";
            response.OrderId = newBillOrder.Id;
            response.OrderNo = newBillOrder.OrderNo;
            response.YiBaoStatus = newBillOrder.YiBaoStatus.GetValueOrDefault();
            response.YiBaoFailedMsg = newBillOrder.Remark ?? "";
            response.PersonalMoney = newBillOrder.PersonalMoney.GetValueOrDefault().ToString("F2");
            response.YiBaoMoney = newBillOrder.YibaoMoney.GetValueOrDefault().ToString("F2");
            response.Items = new List<CreateBillOrderResponse.BillItem>();

            foreach (var item in billDetailResponse.PrescItemList)
            {
                response.Items.Add(new CreateBillOrderResponse.BillItem
                {
                    //Account = item.Account,
                    //ItemPrice = item.ItemPrice.ToDecimalOrDefault().ToString("F4"),
                    Money = item.Money.ToDecimalOrDefault().ToString("F2"),
                    Name = item.ItemName,
                    Type = item.Type
                   // Unit = item.Unit
                });
            }

            return response;
        }

        /// <summary>
        /// 支付缴费单
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        [HttpGet]
        [ActionName("PayBill")]
        public PayBillReponse PayBill(int orderId)
        {
            var azUser = AzUser.GetInApi(Request);
            var order = _ctx.BillOrders.IsStatus(BillOrderExtensions.OrderStatus.未支付)
                .FirstOrDefault(x => x.Id == orderId && x.WxUserId == azUser.UserId);
            if (order == null)
            {
                return new PayBillReponse
                {
                    ResultCode = "1",
                    ResultMsg = "找不到缴费单"
                };
            }

            order.OrderStatus = BillOrderExtensions.OrderStatus.支付中.ToInt32();
            _ctx.SaveChanges();

            // RMQ 16分钟后如果还是支付中则设置支付失败
            var payingTimeoutProducer = new OrderPayingTimeoutProducer();
            payingTimeoutProducer.Publish(new OrderPayingTimeoutMsg
            {
                OrderType = OrderType.门诊缴费订单,
                OrderId = order.Id
            }, 16 * 60 * 1000);

            //组织 微信 js 支付方法 getBrandWCPayRequest 的参数
            var payFee = "";
            if (order.YiBaoStatus == BillOrderExtensions.YiBaoStatus.使用了医保.ToInt32()
                && !string.IsNullOrEmpty(order.YiBaoJydjh))
            {
                payFee = order.PersonalMoney.ToString();
            }
            else
            {
                payFee = order.PrescMoney.ToString();
            }
            var superOpenIds = ConfigurationManager.AppSettings["OpenIdsForPayMin"]
                .Split(" , ", StringSplitOptions.RemoveEmptyEntries);
            if (superOpenIds.Contains(order.WxUserId.ToStringOrDefault()))
            {
                payFee = "0.01";
            }

            //var payRequestParam = TenpayV2Helper.GenerateWxPayParameter("就诊缴费", "BL" + order.OrderNo,
            //    payFee, GetClientIp(), payStartTime, payExpireTime, "Bill/PaySucceed");

            var result = WapPayment.ComposeWapPayParameter(new ComposeWapPayRequest
            {
                NotifyUrl = WebConfigurationManager.AppSettings["AlipayNotify"] + "Bill/PaySucceed",
                CallBackUrl = MessageHelper.GetCallBackUrl("/index/do-bill-callback"),
                MerchantUrl = "",
                OutTradeNo = "BL" + order.OrderNo,
                Subject = "就诊缴费",
                TotalFee = payFee
            });
           var payRequestParam = result.RequestHtml;


            return new PayBillReponse
            {
                ResultCode = "0",
                ResultMsg = "",
                PayString = payRequestParam
            };
        }

        /// <summary>
        /// 用户取消支付
        /// </summary>
        /// <param name="orderId">订单id</param>
        /// <returns></returns>
        [HttpGet]
        [ActionName("PayFailed")]
        public PayFailedResponse PayFailed(int orderId)
        {
            var azUser = AzUser.GetInApi(Request);

            var order = _ctx.BillOrders.IsStatus(BillOrderExtensions.OrderStatus.支付中)
                .FirstOrDefault(x => x.WxUserId == azUser.UserId && x.Id == orderId);
            if (order == null)
            {
                return new PayFailedResponse
                {
                    ResultCode = "1",
                    ResultMsg = "订单不存在"
                };
            }

            order.OrderStatus = BillOrderExtensions.OrderStatus.支付失败.ToInt32();
            _ctx.SaveChanges();

            if (order.YiBaoStatus == BillOrderExtensions.YiBaoStatus.使用了医保.ToInt32())
            {
                order.YiBaoStatus = BillOrderExtensions.YiBaoStatus.取消医保中.ToInt32();
                _ctx.SaveChanges();

                // 执行医保退费操作
                var ybReturnRequest = new YBReturnChargesRequest();
                ybReturnRequest.CardNo = order.CardNo;
                ybReturnRequest.Jydjh = order.YiBaoJydjh;

                YBReturnChargesResponse ybReturnResponse;
                try
                {
                    var httpClient = InHttpClient.GetClient();
                    var responseMsg = httpClient.PostAsJsonAsync("YBWs/YBReturnCharges", ybReturnRequest).Result;
                    responseMsg.EnsureSuccessStatusCode();
                    ybReturnResponse = responseMsg.Content.ReadAsAsync<YBReturnChargesResponse>().Result;

                    if (ybReturnResponse.ResultCode != "0")
                    {
                        order.YiBaoStatus = BillOrderExtensions.YiBaoStatus.取消医保失败.ToInt32();
                        _ctx.SaveChanges();
                    }
                    else
                    {
                        order.YiBaoStatus = BillOrderExtensions.YiBaoStatus.取消了医保.ToInt32();
                        _ctx.SaveChanges();
                    }
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("调用院内医保退费Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                    order.YiBaoStatus = BillOrderExtensions.YiBaoStatus.取消医保失败.ToInt32();
                    _ctx.SaveChanges();
                }
            }

            return new PayFailedResponse
            {
                ResultCode = "0",
                ResultMsg = ""
            };
        }

        /// <summary>
        /// 微信支付通知回调
        /// </summary>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost]
        [ActionName("PaySucceed")]
        public HttpResponseMessage PaySucceed()
        {

            Dictionary<string, string> sPara = AlipayNotifyHelper.GetRequestPost();
            string sign = HttpContext.Current.Request.Form["sign"];
            var result =
                WapPayment.WapPayVerifyNotify(new WapPayVerifyNotifyRequest
                {
                    SPara = sPara,
                    Sign = sign
                });

            if (result != null && result.ResultCode == "0")
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(result.NotifyData);
                string transactionId = xmlDoc.SelectSingleNode("/notify/trade_no")?.InnerText ?? "";
                string trade_status = xmlDoc.SelectSingleNode("/notify/trade_status")?.InnerText ?? "";
                string notify_id = xmlDoc.SelectSingleNode("/notify/notify_id")?.InnerText ?? "";
                var outTradeNo = xmlDoc.SelectSingleNode("/notify/out_trade_no")?.InnerText ?? "";
                decimal total_fee = (xmlDoc.SelectSingleNode("/notify/total_fee")?.InnerText).ToDecimalOrDefault();
                string buyer_id = xmlDoc.SelectSingleNode("/notify/buyer_id")?.InnerText ?? "";
                string timeEnd = xmlDoc.SelectSingleNode("/notify/gmt_payment")?.InnerText;
                string seller_email = xmlDoc.SelectSingleNode("/notify/seller_email")?.InnerText;


                lock (PayNotifyLocker)
                {
                    try
                    {
                        if (_ctx.WxPayNotifyLogs.Any(
                            x => x.TransactionId == transactionId && x.TradeState == 1))
                        {
                            return new HttpResponseMessage
                            {
                                StatusCode = HttpStatusCode.OK,
                                Content = new StringContent("success")
                            };
                        }
                        else
                        {
                            if (trade_status == "TRADE_FINISHED" || trade_status == "TRADE_SUCCESS")
                            {

                                if (outTradeNo.StartsWith("BL"))
                                {
                                    var orderNo = outTradeNo.Substring(2);
                                    var order = _ctx.BillOrders.FirstOrDefault(x => x.OrderNo == orderNo);
                                    if (order != null)
                                    {
                                        //订单状态为待支付，执行his缴费操作
                                        if (order.OrderStatus == BillOrderExtensions.OrderStatus.支付中.ToInt32())
                                        {
                                            order.PayState = BillOrderExtensions.PayState.已付款.ToInt32().ToString();
                                            order.PayTime = timeEnd.ToDateTimeOrDefault();
                                            order.WxTransactionId = transactionId;
                                            order.OrderStatus = BillOrderExtensions.OrderStatus.支付成功.ToInt32();
                                            _ctx.SaveChanges();

                                            // RMQ 执行缴费操作
                                            var pickupingProducer = new OrderPickupingProducer();
                                            pickupingProducer.Publish(new OrderPickupingMsg
                                            {
                                                OrderType = OrderType.门诊缴费订单,
                                                OrderId = order.Id
                                            });
                                        }
                                        //如果订单状态为支付失败（订单15分钟已关闭，用户），或者His缴费失败 added by wesley
                                        else if (order.OrderStatus == BillOrderExtensions.OrderStatus.缴费失败.ToInt32() ||
                                                 order.OrderStatus == BillOrderExtensions.OrderStatus.支付失败.ToInt32())
                                        {
                                            //执行退款操作
                                            var refundingProducer = new OrderRefundingPickupFailedProducer();
                                            refundingProducer.Publish(new OrderRefundingPickupFailedMsg
                                            {
                                                OrderType = OrderType.门诊缴费订单,
                                                OrderId = order.Id
                                            });
                                        }
                                    }
                                }
                            }

                            #region 记录通过验证的支付通知

                            //记录通知日志
                            var orderNotifyLog = new WxPayNotifyLog
                            {
                                ServiceVersion = "2.0",
                                Attach = "",
                                BankBillNo = "",
                                BankType = "AliPay",
                                BuyerAlias = "",
                                Discount = 0,
                                FeeType = 1,
                                InputCharset = "utf-8",
                                NotifyId = notify_id,
                                SignType = "0001",
                                Sign = "", //Request.Form["sign"],
                                SignKeyIndex = 0,
                                TradeMode = 1,
                                PayInfo = "",
                                //Partner = xmlDoc.SelectSingleNode("/notify/seller_id").InnerText,
                                TotalFee = (total_fee*100).ToInt32OrDefault(),
                                TransactionId = transactionId,
                                OutTradeNo = outTradeNo,
                                //TimerEnd = xmlDoc.SelectSingleNode("/notify/gmt_payment").InnerText,
                                TransportFee = 0,
                                ProductFee = (total_fee*100).ToInt32OrDefault(),
                                PostAppId = seller_email,
                                PostTimeStamp = timeEnd,
                                PostNonceStr = "",
                                PostOpenId = buyer_id,
                                PostAppSignature = trade_status,
                                PostIsSubscribe = "1",
                                RecCreateDt = DateTime.Now
                            };
                            if (trade_status == "TRADE_FINISHED" || trade_status == "TRADE_SUCCESS")
                                orderNotifyLog.TradeState = 1;
                            _ctx.WxPayNotifyLogs.Add(orderNotifyLog);
                            _ctx.SaveChanges();

                            #endregion

                            return new HttpResponseMessage
                            {
                                StatusCode = HttpStatusCode.OK,
                                Content = new StringContent("success")
                            };

                        }
                    }
                    catch (System.Data.SqlClient.SqlException sqlEx)
                    {
                        Logger.ErrorFormat("Bill PaySuccessed SqlException Error:{0}",
                            JsonConvert.SerializeObject(sqlEx));
                    }
                    catch (Exception e)
                    {
                        Logger.ErrorFormat("Bill PaySuccessed Error:{0}", JsonConvert.SerializeObject(e));

                    }
                }
            }

            #region 记录验证失败的支付通知

            var unverifiedNotifyLog = new WxPayNotifyLog();
            //unverifiedNotifyLog.PayInfo = Request.RequestUri.AbsoluteUri;
            unverifiedNotifyLog.TradeState = 0;
            unverifiedNotifyLog.RecCreateDt = DateTime.Now;
            _ctx.WxPayNotifyLogs.Add(unverifiedNotifyLog);
            _ctx.SaveChanges();

            #endregion


            return new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.OK,
                Content = new StringContent("fail")
            };
        }


        /// <summary>
        /// 支付宝Wap无密退款支付通知回调
        /// </summary>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost]
        [ActionName("WapPayFail")]
        public HttpResponseMessage WapPayFail()
        {
            try
            {
                Dictionary<string, string> sPara = AlipayNotifyHelper.GetRequestPost();
                string sign = HttpContext.Current.Request.Form["sign"];
                var result =
                    WapPayment.WapPayVerifyNotify(new WapPayVerifyNotifyRequest
                    {
                        SPara = sPara,
                        Sign = sign
                    });

                if (result != null && result.ResultCode == "0")
                {
                    string batch_no = HttpContext.Current.Request.Form["batch_no"];
                    string notify_time = HttpContext.Current.Request.Form["notify_time"];
                    //批量退款数据中转账成功的笔数
                    string success_num = HttpContext.Current.Request.Form["success_num"];
                    //批量退款数据中的详细信息
                    //transcationId^fee^tradestatus
                    string result_details = HttpContext.Current.Request.Form["result_details"];
                    Logger.InfoFormat("WapRefund Info:{0}", result_details);
                    var transctionId = result_details.Split("#").FirstOrDefault().Split("^").FirstOrDefault();
                    var order = _ctx.BillOrders.FirstOrDefault(x => x.WxTransactionId == transctionId);
                    if (order !=null)
                    {
                        // 退款成功
                        order.OrderStatus = PrepayOrderExtensions.OrderStatus.退款成功.ToInt32();
                        order.Remark = "充值失败而退款";
                        order.PayState = PrepayOrderExtensions.PayState.已退款.ToInt32().ToString();
                        order.RefundTime = notify_time.ToDateTimeOrDefault();
                        order.WxRefundId = transctionId;
                        _ctx.SaveChanges();

                        // RMQ 发送用户退费成功通知
                        var msgProducer = new UserMessageProducer();
                        msgProducer.Publish(new UserMessageMsg
                        {
                            Type = UserMessageType.住院预缴金失败退费成功通知,
                            OrderId = order.Id
                        });
                    }
                    return new HttpResponseMessage
                    {
                        StatusCode = HttpStatusCode.OK,
                        Content = new StringContent("success")
                    };
                }

            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("Bill PaySucceed Error,信息：{0}", JsonConvert.SerializeObject(ex));
            }

            return new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.OK,
                Content = new StringContent("fail")
            };
        }

        /// <summary>
        /// 查询缴费执行状态
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        [HttpGet]
        [ActionName("GetBillStatus")]
        public GetBillStatusResponse GetBillStatus(int orderId)
        {
            var azUser = AzUser.GetInApi(Request);
            var order = _ctx.BillOrders.FirstOrDefault(x => x.Id == orderId && x.WxUserId == azUser.UserId);
            if (order == null)
            {
                return new GetBillStatusResponse
                {
                    ResultCode = "1",
                    ResultMsg = "订单不存在"
                };
            }

            if (order.OrderStatus == BillOrderExtensions.OrderStatus.缴费中.ToInt32()
                || order.OrderStatus == BillOrderExtensions.OrderStatus.支付中.ToInt32()
                || order.OrderStatus == BillOrderExtensions.OrderStatus.支付成功.ToInt32())
            {
                return new GetBillStatusResponse
                {
                    ResultCode = "0",
                    ResultMsg = "",
                    BillStatus = "2",
                    FailedMsg = ""
                };
            }

            if (order.OrderStatus == BillOrderExtensions.OrderStatus.缴费成功.ToInt32())
            {
                return new GetBillStatusResponse
                {
                    ResultCode = "0",
                    ResultMsg = (order.Remark ?? "").IndexOf("佑元庄", StringComparison.Ordinal) >= 0
                        ? (order.Remark ?? "") : "",
                    BillStatus = "0",
                    FailedMsg = ""
                };
            }

            return new GetBillStatusResponse
            {
                ResultCode = "0",
                ResultMsg = "",
                BillStatus = "1",
                FailedMsg = ""
            };
        }

        /// <summary>
        /// 支付宝当面付支付通知回调
        /// </summary>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost]
        [ActionName("AlipayNotify")]
        public HttpResponseMessage AlipayNotify()
        {
            try
            {
                Dictionary<string, string> sPara = AlipayNotifyHelper.GetRequestPost();
                string sign = HttpContext.Current.Request.Form["sign"];
                QrCodePayment payment = new QrCodePayment();
                var result =
                    payment.VerifyAcquireNotify(new WapPayVerifyNotifyRequest
                    {
                        SPara = sPara,
                        Sign = sign
                    });

                if (result != null && result.ResultCode == "0")
                {
                    string notify_id = HttpContext.Current.Request.Form["notify_id"];
                    string outTradeNo = HttpContext.Current.Request.Form["out_trade_no"];
                    string trade_no = HttpContext.Current.Request.Form["trade_no"];
                    string trade_status = HttpContext.Current.Request.Form["trade_status"];
                    decimal total_fee = HttpContext.Current.Request.Form["total_amount"].ToDecimalOrDefault();
                    string seller_email = HttpContext.Current.Request.Form["seller_email"];
                    string gmt_payment = HttpContext.Current.Request.Form["gmt_payment"];
                    string openId = HttpContext.Current.Request.Form["open_id"];


                    if (_ctx.WxPayNotifyLogs.Any(
                        x => x.TransactionId == trade_no && x.TradeState == 1))
                    {
                        return new HttpResponseMessage
                        {
                            StatusCode = HttpStatusCode.OK,
                            Content = new StringContent("success")
                        };
                    }
                    if (trade_status == "TRADE_FINISHED" || trade_status == "TRADE_SUCCESS")
                    {
                        long wxUserId =  0;
                        using (var ctx = new GdsfybjyWeiXinEntities())
                        {
                            var wxUser = ctx.WxUsers.FirstOrDefault(x => x.OpenId == openId);
                            if (wxUser == null)
                            {
                                var newWxUser = new WxUser
                                {
                                    OpenId = openId,
                                    LastActiveDt = DateTime.Now,
                                    IsBkMember = 0,
                                    BkMemberId = null,
                                    RecStatus = 1,
                                    RecCreateDt = DateTime.Now,
                                    UserType = "AliPay"
                                };

                                ctx.WxUsers.Add(newWxUser);
                                ctx.SaveChanges();
                                wxUserId = newWxUser.Id;
                            }
                            else
                            {
                                wxUserId = wxUser.Id;
                            }
                        }
                        if (outTradeNo.StartsWith("BL"))
                        {
                            #region 缴费单 执行缴费操作
                            var orderNo = outTradeNo.Substring(2);
                            using (var ctx = new GdsfybjyWeiXinEntities())
                            {
                                var order = ctx.BillOrders.FirstOrDefault(x => x.OrderNo == orderNo);
                                if (order != null)
                                {
                                    if (order.OrderStatus == BillOrderExtensions.OrderStatus.未支付.ToInt32())
                                    {
                                        order.PayState = BillOrderExtensions.PayState.已付款.ToInt32().ToString();
                                        order.OrderStatus = BillOrderExtensions.OrderStatus.支付成功.ToInt32();
                                        //更新订单支付类型
                                        order.AliPayType = "QRCODEOFFLINE";
                                        order.PayTime = DateTime.Parse(gmt_payment);
                                        order.WxTransactionId = trade_no;
                                        order.WxUserId = wxUserId;
                                        ctx.SaveChanges();

                                        // RMQ 执行缴费操作
                                        var pickupingProducer = new OrderPickupingProducer();
                                        pickupingProducer.Publish(new OrderPickupingMsg
                                        {
                                            OrderType = Rmq.Center.OrderType.门诊缴费订单,
                                            OrderId = order.Id
                                        });
                                    }
                                    //如果订单状态为支付失败（订单15分钟已关闭，用户），或者His缴费失败 added by wesley
                                    else if (order.OrderStatus == BillOrderExtensions.OrderStatus.缴费失败.ToInt32() ||
                                             order.OrderStatus == BillOrderExtensions.OrderStatus.支付失败.ToInt32())
                                    {
                                        //执行退款操作
                                        var refundingProducer = new OrderRefundingPickupFailedProducer();
                                        refundingProducer.Publish(new OrderRefundingPickupFailedMsg
                                        {
                                            OrderType = OrderType.门诊缴费订单,
                                            OrderId = order.Id
                                        });
                                    }
                                }
                                else
                                {
                                    //因二维码请求每次生成新的本地单号，当用户扫描旧的二维码支付直接退款给用户
                                    AlipayNotifyHelper.AcquireRefund(trade_no, outTradeNo, total_fee, openId);
                                }
                            }

                            #endregion
                        }
                        else if (outTradeNo.StartsWith("IP"))
                        {
                            #region 住院充值支付成功通知

                            //缴费单 执行缴费操作
                            var orderNo = outTradeNo.Substring(2);
                            using (var ctx = new GdsfybjyWeiXinEntities())
                            {
                                var order = ctx.InpatientPrepayOrders.FirstOrDefault(x => x.OrderNo == orderNo);
                                if (order != null)
                                {

                                    if (order.OrderStatus == PrepayOrderExtensions.OrderStatus.未支付.ToInt32())
                                    {
                                        order.PayState = PrepayOrderExtensions.PayState.已付款.ToInt32().ToString();
                                        order.OrderStatus = PrepayOrderExtensions.OrderStatus.支付成功.ToInt32();
                                        //更新订单支付类型
                                        order.AliPayType = "QRCODEOFFLINE";
                                        order.PayTime = DateTime.Parse(gmt_payment);
                                        order.WxTransactionId = trade_no;
                                        order.OpenId = openId;
                                        ctx.SaveChanges();


                                        // RMQ 执行缴纳预缴金操作
                                        var pickupingProducer = new OrderPickupingProducer();
                                        pickupingProducer.Publish(new OrderPickupingMsg
                                        {
                                            OrderType = Rmq.Center.OrderType.住院预缴金订单,
                                            OrderId = order.Id
                                        });

                                    }
                                    else if (order.OrderStatus == PrepayOrderExtensions.OrderStatus.缴费失败.ToInt32())
                                    {
                                        //His缴费失败，执行退款操作
                                        var refundingProducer = new OrderRefundingPickupFailedProducer();
                                        refundingProducer.Publish(new OrderRefundingPickupFailedMsg
                                        {
                                            OrderType = OrderType.住院预缴金订单,
                                            OrderId = order.Id
                                        });
                                    }
                                }
                                else
                                {
                                    AlipayNotifyHelper.AcquireRefund(trade_no, outTradeNo, total_fee, openId);
                                }
                            }

                            #endregion
                        }
                    }

                    #region 记录通过验证的支付通知

                    //记录通知日志
                    var orderNotifyLog = new WxPayNotifyLog
                    {
                        ServiceVersion = "2.0",
                        Attach = "",
                        BankBillNo = "",
                        BankType = "AliPay",
                        BuyerAlias = "",
                        Discount = 0,
                        FeeType = 1,
                        InputCharset = "utf-8",
                        NotifyId = notify_id,
                        SignType = "0001",
                        Sign = "", //Request.Form["sign"],
                        SignKeyIndex = 0,
                        TradeMode = 1,
                        PayInfo = "",
                        //Partner = xmlDoc.SelectSingleNode("/notify/seller_id").InnerText,
                        TotalFee = (total_fee*100).ToInt32OrDefault(),
                        TransactionId = trade_no,
                        OutTradeNo = outTradeNo,
                        //TimerEnd = xmlDoc.SelectSingleNode("/notify/gmt_payment").InnerText,
                        TransportFee = 0,
                        ProductFee = (total_fee*100).ToInt32OrDefault(),
                        PostAppId = seller_email,
                        PostTimeStamp = gmt_payment,
                        PostNonceStr = "",
                        PostOpenId = openId,
                        PostAppSignature = trade_status,
                        PostIsSubscribe = "1",
                        RecCreateDt = DateTime.Now
                    };
                    if (trade_status == "TRADE_FINISHED" || trade_status == "TRADE_SUCCESS")
                        orderNotifyLog.TradeState = 1;
                    _ctx.WxPayNotifyLogs.Add(orderNotifyLog);
                    _ctx.SaveChanges();

                    #endregion

                    return new HttpResponseMessage
                    {
                        StatusCode = HttpStatusCode.OK,
                        Content = new StringContent("success")
                    };
                }

                #region 记录验证失败的支付通知

                var unverifiedNotifyLog = new WxPayNotifyLog();
                //unverifiedNotifyLog.PayInfo = Request.RequestUri.AbsoluteUri;
                unverifiedNotifyLog.TradeState = 0;
                unverifiedNotifyLog.RecCreateDt = DateTime.Now;
                _ctx.WxPayNotifyLogs.Add(unverifiedNotifyLog);
                _ctx.SaveChanges();

                #endregion
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("QRCodeOFFLINE AlipayNotify Error,信息：{0}", JsonConvert.SerializeObject(ex));
            }

            return new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.OK,
                Content = new StringContent("fail")
            };
        }

        /// <summary>
        /// 生成挂号订单号
        /// </summary>
        /// <returns></returns>
        public static string GenerateNewOrderNo()
        {
            var orderNo = "AL" + DateTime.Now.Date.ToString("yyyyMMdd");
            lock (OrderNoLocker)
            {
                orderNo += (DateTime.Now - DateTime.Now.Date).TotalMilliseconds.ToString("00000000");
                Thread.Sleep(1);
            }

            return orderNo;
        }

        public string GetClientIp()
        {
            if (Request.Properties.ContainsKey("MS_HttpContext"))
            {
                string ip = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                //判断是否有代理服务器
                if (string.IsNullOrEmpty(ip))
                {
                    //没有代理服务器,如果有代理服务器获取的是代理服务器的IP
                    ip = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
                }

                string pattrn = @"(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])";
                if (!string.IsNullOrEmpty(ip) && System.Text.RegularExpressions.Regex.IsMatch(ip, pattrn))
                {
                    return ip;
                }

                return "127.0.0.1";
            }
            else
            {
                return "127.0.0.1";
            }
        }
    }
}
